Tack.Console = new Class({
	initialize: function (container, player, debug) {
		this.history = [''];
		this.historyIndex = 0;

		this.html = {
			main: new Element('div', { 'class': 'console' }),
			output: new Element('div'),
			input: new Element('input', { events: {
				keydown: this.handleKeyDown.bindWithEvent(this),
				keyup: this.handleKeyUp.bindWithEvent(this)
			} })
		};

		this.scroll = new Fx.Scroll(this.html.output);

		this.html.main.adopt(this.html.output, this.html.input);
		$(container).adopt(this.html.main);

		this.setDebug(debug);
		this.setPlayer(player);
	},

	handleKeyUp: function (e) {
		if (['up', 'down', 'enter'].contains(e.key)) return;

		this.historyIndex = this.history.length - 1;
		this.history[this.historyIndex] = this.html.input.get('value');
	},

	handleKeyDown: function (e) {
		if (e.key == 'up' && this.historyIndex > 0) {
			this.historyIndex--;
			this.html.input.set('value', this.history[this.historyIndex]);
		} else if (e.key == 'down' && this.historyIndex < this.history.length - 1) {
			this.historyIndex++;
			this.html.input.set('value', this.history[this.historyIndex]);
		}

		if (e.key != 'enter') return;
		e.stop();

		var value = this.html.input.get('value').trim();
		if (!value) return;

		var h = this.history, l = h.length;
		if (h[l - 2] != value) h[l - 1] = value; else l--;
		h[this.historyIndex = l] = '';

		this.html.input.set('value', '');
		this.write('> ' + value, 'input');

		if (this.debug) {
			switch (value.toLowerCase()) {
				case 'cls':
					this.html.output.set('text', '');
					return;

				case 'help':
					this.write('CLS    Removes all text from the console.', 'debug');
					this.write('HELP   Shows this help.', 'debug');
					this.write('RESET  Resets the current game session. All states will be turned off and the player will be moved to the starting scene.', 'debug');
					return;

				case 'reset':
					this.player.endGame();
					this.player.play();
					return;
			}
		}

		try {
			this.player.play(value);
		} catch (e) {
			this.write(this.debug ? 'Exception occurred: \'' + e + '\'' : 'An error occurred. Please notify the author of this game.', 'error');
		}

		this.html.input.focus();
	},

	setDebug: function (flag) {
		if (flag) {
			this.debug = true;
			this.write('Debug mode enabled. Type \'help\' for a list of available commands.', 'debug');
		} else {
			this.debug = false;
		}
	},

	setPlayer: function (player) {
		if (player == this.player) return;

		if (this.player) this.player.unsubscribe(this);
		this.player = player;
		if (player) player.subscribe(this);
	},

	write: function (text, type) {
		if (!text) return;
		if (type == 'debug' && !this.debug) return;

		text = text.replace(/	/g, '\u00A0 ').replace(/	/g, ' \u00A0');

		var e;
		this.html.output.adopt(e = new Element('span', { text: text }));
		if (type) e.addClass(type);
		e.set('html', e.get('html').replace(/\r\n|\r|\n/g, '<br/>'));

		this.scroll.cancel();
		this.scroll.toBottom();
	}
});
